#include "integer_table.h"
#include <algorithm>

const std::set<SeaDrip::Coordinate2D> IntegerTable::GetSaddles() const
{
    std::set<SeaDrip::Coordinate2D> max_in_lines, min_in_rows, ret;
    for (unsigned int line_index = 0; line_index < height; line_index++)
    {
        for (auto max_val_index : this->MaxIndexesInLine(line_index))
        {
            max_in_lines.insert(SeaDrip::Coordinate2D(max_val_index, line_index));
        }
    }
    for (unsigned int row_index = 0; row_index < width; row_index++)
    {
        for (auto min_val_index : this->MinIndexesInRow(row_index))
        {
            min_in_rows.insert(SeaDrip::Coordinate2D(row_index, min_val_index));
        }
    }

    std::set_intersection(
        max_in_lines.begin(), max_in_lines.end(),
        min_in_rows.begin(), min_in_rows.end(),
        std::inserter(ret, ret.begin())
    );
    return ret;
}

const std::set<unsigned int> IntegerTable::MaxIndexesInLine(const unsigned int line) const
{
    unsigned int max_val = (*this)[line][0];
    for (unsigned int i = 1; i < width; i++)
    {
        int cursor = (*this)[line][i];
        if (cursor > max_val)
        {
            max_val = cursor;
        }
    }

    std::set<unsigned int> ret;
    for (unsigned int i = 0; i < width; i++)
    {
        if ((*this)[line][i] == max_val)
        {
            ret.insert(i);
        }
    }
    return ret;
}

const std::set<unsigned int> IntegerTable::MinIndexesInRow(const unsigned int row) const
{
    unsigned int min_val = (*this)[0][row];
    for (unsigned int i = 1; i < height; i++)
    {
        int cursor = (*this)[i][row];
        if (cursor < min_val)
        {
            min_val = cursor;
        }
    }

    std::set<unsigned int> ret;
    for (unsigned int i=0; i < height; i++)
    {
        if ((*this)[i][row] == min_val)
        {
            ret.insert(i);
        }
    }
    return ret;
}
